//--------------------------------------------------------------------------------------------------
//                                                   ___  __  __  __  __  __  __  __    __  __  ___ 
// Copyright 2010, Koert van der Veer.              / __)(  )(  )(  \/  )(  )(  )(  )  (  )(  )/ __)
// Licensed under the Apache License,              ( (__  )(__)(  )    (  )(__)(  )(__  )(__)( \__ \
// version 2.0; ("the License")                     \___)(______)(_/\/\_)(______)(____)(______)(___/

// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at 
//     http://www.apache.org/licenses/LICENSE-2.0 
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under
// the License. 
//--------------------------------------------------------------------------------------------------
// This file is part of cumulus,  an memory manager implementation in C++.  Details are discussed in
// my blog,  which can be found at http://ondergetekende.nl.  Comments,  suggestions and bug reports
// are welcome. They can be added as comments at the blog. Be advised that in its current form, this
// code is most likely not production ready; it simply hasn't been tested sufficiently. 
//--------------------------------------------------------------------------------------------------
// Cumulus::Interface
// A memory allocator which  does nothing. It serves as definition of the interface which all layers
// should implement.  Besides that, it can be used as a stub: all methods are correctly implemented.
// -------------------------------------------------------------------------------------------------

#pragma once

#include "misc.h"

namespace Cumulus
{

class Interface : public NonAssignable
{
public:

	// The minimum alignment for all mallocs.
    // All pointers returned my Malloc are at least of this alignment.
	static const size_t MinAlignment = 0x01;

	// The minimum size for all mallocs, while smaller requests are valid,
        // they will be rounded up to this size.
	static const size_t MinSize = 0x01;

	// Support flags for various features
	static const bool IsThreadSafe = true;
	static const bool SupportsEnumeration = false;
	static const bool SupportsBackwardEnumeration = false;

	/// Returns a pointer to the a new piece of memory, of at least Size.
    /// After the call, Size may be changed to a larger number. In that case,
    /// the caller may use up Size bytes. Note that successive calls to GetSize
    /// may return a different (larger) number.
    /// @param  Size	in/out The requested size of the new memory allocation. Must be > 0. 
	///					Post: the size usable for writes, larger than
    /// @return			A pointer to the new memory block, or NULL if the allocation was
    /// 				not successful.
	void* Malloc( size_t& Size ) 
	{
		return NULL; 
	}

	/// Returns ownership of a block of memory to the memory manager.        
	/// @param  Memory	Pointer to the allocation be released. Must be a valid pointer, as 
	//					previously returned by Malloc. (NULL is invalid)
	void Free( void* Memory ) 
	{
	}

	/// Returns the client usable size for the provided pointer
    /// This is guaranteed to be equal or larger than the request size provided to Malloc.
    /// Successive calls to GetSize will return the same value, unless Resize was called earlier.
    /// @param Memory	Pointer to allocation queried. Must be a valid pointer, as previously 
    ///					returned by Malloc. Any other pointer (including NULL) is invalid.
	size_t GetSize( void* Memory )
	{
		return 0;
	}

	/// Tries to change the size of the allocated block to at least NewSize.
	/// After the call, NewSize may be changed to a larger number. In that case,
	/// the caller may use up Size bytes. Note that successive calls to GetSize
	/// may return a different (larger) number.
	/// @param Memory	Pointer to allocation to be modified. Must be a valid pointer, as previously
	///					returned by Malloc. Any other pointer (including NULL) is invalid.
	/// @param NewSize	in/out The new size for the allocation
	/// @return			TRUE if the resize operation was successful.
	bool Resize( void* Memory, size_t& NewSize )
	{
		return false;
	}


	/// Interface for enumerable layers. Enumeration is in no specific order.
	/// If SupportsEnumeration is TRUE, between calls two Malloc or Free, the following is true:
	/// * Enumeration order is the same for successive enumeration. 
	/// * All allocations will be visited by enumerating
	/// * Every pointer returned by these methods was previously returned by a call to Malloc. 
	/// If SupportsReverseIteration is TRUE, the order of the iteration with GetLast and GetPrevious
	/// is guaranteed to be the reverse of the iteration using GetFirst and GetNext.
	/// Even if SupportsEnumeration and SupportsReverseIteration is FALSE, a layer could implement a
	/// best-effort implementation.

	/// Enumerator for memory allocations.
	/// @param Memory	Pointer to allocation queried. Must be a valid pointer, as previously 
	///					returned by Malloc, or NULL to request the first Allocation.
	/// @return			A pointer to the memory allocation after Memory.
	void* GetNext( void* Memory ) { return NULL; }

	/// Reverse enumerator for memory allocations.
	/// @param Memory	Pointer to allocation queried. Must be a valid pointer, as previously 
	///					returned by Malloc, or NULL to request the last Allocation.
	/// @return			A pointer to the memory allocation after Memory.
	void* GetPrevious( void* Memory ) { return NULL; }
};

}